package com.lanhai;

import java.io.File;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.exceptions.WebsocketNotConnectedException;
import org.java_websocket.handshake.ServerHandshake;

import com.alibaba.fastjson.JSON;
import com.lanhai.action.AgvDispatchAction;
import com.lanhai.enums.AgvState;
import com.lanhai.enums.Step;
import com.lanhai.enums.TransferType;
import com.lanhai.javaBean.AgvBean;
import com.lanhai.javaBean.CacheShelfBean;
import com.lanhai.javaBean.ControlAreaBean;
import com.lanhai.javaBean.FreeAreaBean;
import com.lanhai.javaBean.GuidepostBean;
import com.lanhai.javaBean.LimitAreaBean;
import com.lanhai.javaBean.ParamBean;
import com.lanhai.javaBean.ParkBean;
import com.lanhai.javaBean.PathBean;
import com.lanhai.javaBean.PathLockBean;
import com.lanhai.javaBean.StationBean;
import com.lanhai.model.Agv;
import com.lanhai.model.CacheShelf;
import com.lanhai.model.ControlArea;
import com.lanhai.model.FreeArea;
import com.lanhai.model.Guidepost;
import com.lanhai.model.Job;
import com.lanhai.model.LimitArea;
import com.lanhai.model.Park;
import com.lanhai.model.ParkGroup;
import com.lanhai.model.Path;
import com.lanhai.model.PathLock;
import com.lanhai.model.Station;
import com.lanhai.model.TrafficWait;
import com.lanhai.system.Accept4Agv;
import com.lanhai.system.Accept4Park;
import com.lanhai.system.DeleteHandler;
import com.lanhai.system.LoginHandler;
import com.lanhai.system.QueryHandler;
import com.lanhai.system.SearchHandler;
import com.lanhai.system.SubmitHandler;
import com.lanhai.utils.CommandUtil;
import com.lanhai.utils.DateUtil;
import com.lanhai.utils.FileUtil;
import com.lanhai.utils.HexUtil;
import com.lanhai.utils.PropsUtil;
import com.lanhai.utils.UDPUtil;
import com.mybatis.dao.ParkDao;
import com.mybatis.dao.PathDao;
import com.sun.net.httpserver.HttpServer;

public class Main {

	private static final Logger logger = Logger.getLogger(Main.class);
	private static final Logger input = Logger.getLogger("input");
	private static final Logger output = Logger.getLogger("output");
	public static SqlSessionFactory sqlSessionFactory;
	public static Properties props;
	public static String localStationIpAddress;
	/**
	 * 低电量充电时间
	 */
	public static int lowBatteryChargerTimes;
	public MainAction mainAction;

	public String localIp;// 本地IP地址
	public String controlIp;// 控制台IP地址
	public int chargeDuration;// 充电时长
	public String PCName;// 本机名称
	public String dataPath;// 基础数据路径
	public String dbUrl;// 数据库连接地址
	public String dbDriver;// 数据库访问驱动
	public String dbUserName;// 数据库用户名
	public String dbPassword;// 数据库密码
//	public DruidDataSource dataSource;//数据库连接池

	public ExecutorService pool;

	/**
	 * AgvMap
	 */
	public Map<Integer, Agv> agvMap;

	/**
	 * GuidepostMap(路标)
	 */
	public Map<Integer, Guidepost> guidepostMap;
	/**
	 * 交管区Map
	 */
	public Map<Integer, ControlArea> controlAreaMap;
	public List<TrafficWait> waitAgvList;
	/**
	 * 自由区
	 */
	public Map<Integer, FreeArea> freeAreaMap;
	/**
	 * 任务列表
	 */
	public List<Job> jobList;
	/**
	 * 站点（停泊位）列表
	 */
	public Map<Integer, Park> parkMap;
	/**
	 * 站点分组列表
	 */
	public Map<Integer, ParkGroup> parkGroupMap;
	/**
	 * 限行区Map
	 */
	public Map<Integer, LimitArea> limitAreaMap;
	/**
	 * 限行AGV暂停的AGV key:限行入口标号，value:agvId
	 */
	public Map<Integer, Integer> limitAgvMap;
	/**
	 * 站点Map
	 */
	public Map<String, Station> stationMap;
	/**
	 * 缓存列表
	 */
	public Map<String, CacheShelf> cacheShelfMap;
	/**
	 * 等待离开单行区AgvId列表
	 */
	public List<Path> pathList;
	/**
	 * 临时停靠点
	 */
	public List<Park> waitParkList;

	/**
	 * 行车线路
	 */
	public Map<String, Path> mapPathMap = new HashMap<String, Path>();
	/**
	 * 行车线路锁
	 */
	public Map<Integer, PathLock> pathLockMap = new HashMap<Integer, PathLock>();
	/**
	 * 系统参数列表
	 */
	public List<Map<String, String>> paramList;

	private static ExecutorService httpPool;

	public static WebSocketClient wsClient;
	public static Date sfTime;

	public static void main(String[] args) {
		Main main = new Main();
		main.init();
	}

	/**
	 * 初始化系统数据
	 */
	public void init() {
		props = PropsUtil.loadProps("jdbc.properties");
		this.dbUrl = PropsUtil.getString(props, "url");
		this.dbDriver = PropsUtil.getString(props, "driverClassName");
		this.dataPath = PropsUtil.getString(props, "dataPath");
		this.dbUserName = PropsUtil.getString(props, "username");
		this.dbPassword = PropsUtil.getString(props, "password");
		try {
			InetAddress addr = InetAddress.getLocalHost();
			PCName = addr.getHostName().toString();
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 指定全局配置文件
		String resource = "mybatis-config.xml";
		// 读取配置文件
		InputStream inputStream = null;
		try {
			inputStream = Resources.getResourceAsStream(resource);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 构建sqlSessionFactory
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

		loadBaseData();
		mainAction = new MainAction();
		mainAction.init(this);
		pool = Executors.newCachedThreadPool();
		logger.info("执行初始化方法！！！");
		sfTime = new Date();
		cronJob();
		cronJob4ZDES();
		initSocket();
		try {
			HttpServer server = HttpServer.create(new InetSocketAddress(8001), 0);
			QueryHandler bphh = new QueryHandler();
			bphh.init(this);
			server.createContext("/queryData", bphh);
			LoginHandler sh = new LoginHandler();
			sh.init(this);
			server.createContext("/login", sh);
			DeleteHandler dh = new DeleteHandler();
			dh.init(this);
			server.createContext("/del", dh);
			SubmitHandler submit = new SubmitHandler();
			submit.init(this);
			server.createContext("/submit", submit);
			SearchHandler search = new SearchHandler();
			search.init(this);
			server.createContext("/search", search);
			// 设置线程执行器
			httpPool = Executors.newCachedThreadPool();
			server.setExecutor(httpPool);
			server.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
		// webSocketConn();
		logger.info("本机名称：" + PCName + ",IP:" + localIp + ",充电时长：" + chargeDuration);
		logger.info("初始化成功！！！");
	};

	/**
	 * 每秒钟执行一次定时任务 delay 1 seconds, and excute every 2 seconds
	 */
	public void cronJob() {
		ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
		scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
//				logger.info("定时任务开始时间：" + DateUtil.getTimeDate(new Date()));
//				logger.info("delay 1 seconds, and excute every 2 seconds");
				// 定时向前端界面推送数据
				try {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("agvMap", agvMap);
					// map.put("controlAreaMap", controlAreaMap);
					// map.put("jobList", jobList);
					map.put("stationMap", stationMap);
					String jsonStr = JSON.toJSONString(map);
					byte[] data = jsonStr.getBytes();
					String controlIp = PropsUtil.getString(props, "controlIp");
					if (controlIp != null) {
						int port = PropsUtil.getNumber(props, "netPort");
						UDPUtil.sendData4Byte(data, controlIp, port);
					}
					// 检查是否需要重连websocket
					if (wsClient == null) {
						logger.info("需要重连websocket!!!!");
						webSocketConn();
					}
				} catch (WebsocketNotConnectedException e) {
					logger.error("没有websocket连接！");
					wsClient = null;
					e.printStackTrace();
				} catch (Exception e) {
					logger.error("Exception", e);
				}

				// 如果超过一定时间没有收到AGV的数据，则将其状态更新为下线
				Date currentDate = new Date();
				long t2 = currentDate.getTime();
				try {
					for (Map.Entry<Integer, Agv> m : agvMap.entrySet()) {
						Agv a = m.getValue();
						if (a.getLastReceiveTime() == null) {
							mainAction.agvAction.clearControlArea(a);
						} else {
							long lt = a.getLastReceiveTime().getTime();
							long tt = (t2 - lt) / 1000;
							if (tt > 600) {// 30秒
//								a.setState(AgvState.LX.getCode());// 更新状态为“离线”
//								a.setCtrlState(AgvState.LX.getCode());// 更新调度状态为“离线”
//								a.setStep(0);
//								a.setParkId(0);// 停靠工位置“0”
//								a.setParkName("");
//								a.setGoal(0);// 目的地标号置“0”
//								a.setLastPoint(0);// 最后到达地标置“0”
//								a.setStartPoint(0);
//								a.setEndPoint(0);
//								a.setIsMultiPath(0);
//								// 如果离线AGV有占用交管区，要释放交管
								mainAction.agvAction.clearControlArea(a);
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}

				// 移动制绒工序的待命AGV
				try {
					mainAction.agvAction.shift4qyCharger();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[前氧充电桩]抛错：", e);
				}
				
				try {
					mainAction.agvAction.shiftAgv4zrs();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[制绒上料]抛错：", e);
				}
				
				try {
					mainAction.agvAction.shift4KSCharger();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[扩散充电桩到制绒选择点]抛错：", e);
				}
				
				try {
					mainAction.agvAction.shiftAgv4zrx();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[制绒下料]抛错：", e);
				}
				
				try {
					mainAction.agvAction.shiftAgv4kss();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[扩散]抛错：", e);
				}

				try {
					mainAction.agvAction.shiftAgv4ksx();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[扩散]抛错：", e);
				}
				try {
					mainAction.agvAction.shiftAgv4se();
//					mainAction.agvAction.shiftAgv4se2();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[SE]抛错：", e);
				}
				try {
//					mainAction.agvAction.shiftAgv4ly2();
//					mainAction.agvAction.shiftAgv4qy();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[前氧]抛错：", e);
				}

				try {
					mainAction.agvAction.shift4jp();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[碱抛上]抛错：", e);
				}

				try {
					mainAction.agvAction.shift4jpfk();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[碱抛返空]抛错：", e);
				}

				try {
					mainAction.agvAction.shiftAgv4hy();
				} catch (Exception e) {
					logger.error("定时任务的移动AGV方法[后氧]抛错：", e);
				}

				// 将泊位的停靠agvId更新到temp_park临时表
				for (Map.Entry<Integer, Park> mp : parkMap.entrySet()) {
					try {
						mainAction.updateTempPark(mp.getValue().getId());
					} catch (Exception e) {
						logger.error("Exception:", e);
					}
				}

				// 超过一定时间没有收到机台的数据，则将其等待状态更新为“0”
				try {
					for (Map.Entry<String, Station> s : stationMap.entrySet()) {
						Station station = s.getValue();
						if (station.getLastReceiveTime() == null) {
							station.setIsWait((byte) 0);
							station.setIsWait2((byte) 0);
							// station.setJoinAgvId(0);
						} else {
							long lt = station.getLastReceiveTime().getTime();
							long tt = (t2 - lt) / 1000;
							if ((station.getStep() == Step.ZRS.getCode() || station.getStep() == Step.ZRX.getCode())
									&& tt > 3) {
//								station.setIsWait((byte) 0);
//								station.setIsWait2((byte) 0);
							}
							if (tt > 4) {// 2秒
								// station.setIsWait((byte)0);
								// station.setIsWait2((byte)0);
								List<CacheShelf> ca = mainAction.taskAction.getcacheShelf4Id(station);
								if (ca.size() > 0) {
									for (CacheShelf cacheShelf : ca) {
										cacheShelf.setInFlag(0);
										cacheShelf.setOutFlag(0);
									}
								}
								// station.setJoinAgvId(0);
							}
						}
						// 定时清除状态，如果没有车停在改工位
						boolean isClear = true;
						for (Map.Entry<Integer, Agv> m : agvMap.entrySet()) {
							Agv agv = m.getValue();
							Guidepost gp = GuidepostBean.contrast(mainAction.main.guidepostMap, agv.getCurrentX(),
									agv.getCurrentY(), AgvDispatchAction.RADIUS);// 判断当前座标是否在某个站点的半径范围内（路标，x坐标，y坐标，半径为30）
							if (gp != null && gp.getNum() == station.getInNum()) {
								isClear = false;
							}
						}
						if (isClear && !station.getIpAddress().equals("0")) {
							if (station.getStep() == Step.KSS.getCode() || station.getStep() == Step.KSX.getCode()
									|| station.getStep() == Step.HYS.getCode()
									|| station.getStep() == Step.HYX.getCode() || station.getStep() == Step.QY.getCode()
									|| station.getStep() == Step.JPS.getCode()
									|| station.getStep() == Step.JPX.getCode()
									|| station.getStep() == Step.JPFK.getCode()) {
								Park park = mainAction.getParkByStationName(station.getName());
								if (park != null) {
									byte[] mData = HexUtil.hexToByte(station.getSname() + "000000000000000000");
									String note = "没有车辆在该机台，清除该机台状态";
									sendDataToPark(mData, park, note);
								}
							}

							if (station.getStep() == Step.ZRS.getCode() || station.getStep() == Step.ZRX.getCode()) {
								Park park = mainAction.getParkByStationName(station.getName());
								if (park != null) {
									byte[] mData = HexUtil.hexToByte(station.getSname() + "000000000000000000");
									String note = "没有车辆在该机台，清除该机台状态";
									sendDataToParkWithLocalPort(mData, park, note);
								}
							}

							// PE背膜自动发0清除状态
							if (station.getStep() == Step.PEBX.getCode() || station.getStep() == Step.PEBX.getCode()
									|| station.getStep() == Step.PEZ.getCode()
									|| station.getStep() == Step.PEZX.getCode()) {
								List<Station> staList = new ArrayList<Station>();
								for (Map.Entry<String, Station> m : stationMap.entrySet()) {
									if (m.getValue().getIpAddress().equals(station.getIpAddress())
											&& m.getValue().getPort() == station.getPort()
											&& !m.getValue().getName().equals(station.getName())) {
										staList.add(m.getValue());
									}
								}
								boolean isClear2 = true;
								if (staList.size() > 0) {
									for (Station sta : staList) {
										for (Map.Entry<Integer, Agv> m : agvMap.entrySet()) {
											Agv agv = m.getValue();
											if (agv.getLastPoint() == sta.getInNum()) {
												isClear2 = false;
											}
										}
									}
								}

								if (isClear2) {
									Park park = mainAction.getParkByStationName(station.getName());
									if (park != null) {
										byte[] mData = HexUtil.hexToByte(station.getSname() + "000000000000000000");
										String note = "没有车辆在该机台，清除该机台状态";
										sendDataToPark(mData, park, note);
									}
								}

							}

						}

					}
				} catch (Exception e) {
					e.printStackTrace();
				}

				// 将AGV的数据更新到temp_agv临时表
				for (Map.Entry<Integer, Agv> ma : agvMap.entrySet()) {
					try {
						List<Map<String, Object>> tempAgvs = AgvBean.loadTempData(sqlSessionFactory);
						boolean insertFlag = true;
						for (Map<String, Object> a : tempAgvs) {
							int agvId = (Integer) a.get("id");
							if (agvId == ma.getValue().getId())
								insertFlag = false;
						}

						// insert加入条件
						if (insertFlag) {
							mainAction.insertTempAgv(ma.getValue());
						} else {
							mainAction.updateTempAgv(ma.getValue());
						}

					} catch (Exception e) {
						logger.error("Exception:", e);
					}
				}

				// 充电计时，让AGV到下道工序的待命区
//				stopCharge();
//				int threadCount = ((ThreadPoolExecutor) pool).getActiveCount();
//				long taskCount = ((ThreadPoolExecutor) pool).getTaskCount();
//				long completedTaskCount = ((ThreadPoolExecutor) pool).getCompletedTaskCount();
//				logger.info("=====[pool]活动线程:" + threadCount + ",总线程：" + taskCount + ",完成：" + completedTaskCount + "=====");
//				logger.info("定时任务结束时间：" + DateUtil.getTimeDate(new Date()));
			}
		}, 1, 2, TimeUnit.SECONDS);
	}

	/**
	 * 每秒钟执行一次定时任务,向中电二所相关类型机台发送数据流
	 */
	int count4ZDES = 1;// 中电二所心跳包初始化

	public void cronJob4ZDES() {
		ScheduledExecutorService scheduledThreadPools = Executors.newScheduledThreadPool(6);
		scheduledThreadPools.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				try {
					for (Map.Entry<String, Station> m : stationMap.entrySet()) {
						Station station = m.getValue();
						if (station.getStep() == Step.ZRS.getCode() || station.getStep() == Step.ZRX.getCode()) {
							Park park = mainAction.getParkByStationName(station.getName());
							if (!park.getXtIpAddress().equals("0") && park.getXtPort() != 0) {
								byte[] data = new byte[1];
								data[0] = (byte) count4ZDES;
								String note = "向中电二所机台发送定时数据流：" + HexUtil.byte2HexStr(data);
								sendDataToZDES(data, park, note);
							}
						}
					}
					if (count4ZDES == 100) {
						count4ZDES = 1;
					} else {
						count4ZDES++;
					}
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		}, 500, 500, TimeUnit.MILLISECONDS);
	}

	/**
	 * 加载系统的基础数据
	 */
	public void loadBaseData() {
		limitAgvMap = new HashMap<Integer, Integer>();// 限行Agv列表
		waitAgvList = new ArrayList<TrafficWait>();
		// 加载交管区列表
		controlAreaMap = new HashMap<Integer, ControlArea>();
		List<ControlArea> controlAreaList = ControlAreaBean.loadData(sqlSessionFactory);
		for (ControlArea ca : controlAreaList) {
			controlAreaMap.put(ca.getId(), ca);
		}
		// 加载交管区列表
		freeAreaMap = new HashMap<Integer, FreeArea>();
		List<FreeArea> freeAreaList = FreeAreaBean.loadData(sqlSessionFactory);
		for (FreeArea fa : freeAreaList) {
			freeAreaMap.put(fa.getId(), fa);
		}
		// 加载AGV列表
		agvMap = new HashMap<Integer, Agv>();
		List<Agv> agvList = AgvBean.loadData(sqlSessionFactory);
		for (Agv agv : agvList) {
			agv.setParkName("");
			agv.setLastData("");
			agv.setLastTime("");
			agv.setCtrlNote("");
			agv.setCtrlCommandStr("");
			agv.setCurrentX(0);
			agv.setCurrentY(0);
			agv.setChargerTimes(new Date());
			agvMap.put(agv.getId(), agv);
		}
		List<Map<String, Object>> tempAgvs = AgvBean.loadTempData(sqlSessionFactory);
		for (Map<String, Object> a : tempAgvs) {
			int agvId = (Integer) a.get("id");
			Agv agv = agvMap.get(agvId);
			agv.setLastPoint((Integer) a.get("lastPoint"));
			agv.setLastJoinStationId((Integer) a.get("lastJoinStationId"));
			agv.setLastJoinStationName((String) a.get("lastJoinStationName"));
			agv.setNextDot((String) a.get("nextDot"));
			agv.setStartPoint((Integer) a.get("startPoint"));
			agv.setEndPoint((Integer) a.get("endPoint"));
			agv.setIsMultiPath((Integer) a.get("isMultiPath"));
			agv.setpGroup((Integer) a.get("pGroup"));
			agv.setpType((Integer) a.get("pType"));
			agv.setGoal((Integer) a.get("goal"));
			agv.setParkId((Integer) a.get("parkId"));
			agv.setParkName((String) a.get("parkName"));
			agv.setWaitParkTimes((Date) a.get("waitParkTime"));
			agv.setLineLockGroup((Integer) a.get("lockGroup"));
			agv.setIsStep((Integer) a.get("isStep"));
			agv.setNextStep((Integer)a.get("nextStep"));
			agvMap.put(agv.getId(), agv);
		}
		// 加载路标列表
		guidepostMap = new HashMap<Integer, Guidepost>();
		List<Guidepost> guidepost = GuidepostBean.loadData(sqlSessionFactory);
		for (Guidepost gd : guidepost) {
			guidepostMap.put(gd.getNum(), gd);
		}
		// 加载站点（停泊位）
		parkMap = new HashMap<Integer, Park>();
		waitParkList = new ArrayList<Park>();
		List<Park> parkList = ParkBean.loadData(sqlSessionFactory);
		for (Park park : parkList) {
			parkMap.put(park.getId(), park);
			if (park.getType() == 4) {// 类型为临时停靠点
				waitParkList.add(park);
			}
		}
		List<Map<String, Object>> tempParks = ParkBean.loadTempData(sqlSessionFactory);
		for (Map<String, Object> tp : tempParks) {
			int parkId = (Integer) tp.get("id");
			Park p = parkMap.get(parkId);
			if (p != null) {
				p.setAgvId((Integer) tp.get("agvId"));
				parkMap.put(p.getId(), p);
			}
		}
		// 加载缓存列表
		cacheShelfMap = new HashMap<String, CacheShelf>();
		List<CacheShelf> cacheShelfs = CacheShelfBean.loadData(sqlSessionFactory);
		for (CacheShelf cs : cacheShelfs) {
			cacheShelfMap.put(cs.getName(), cs);
		}

		// 加载行车线路
		pathList = PathBean.loadData(sqlSessionFactory);
		if (pathList.size() > 0) {
			for (Path mp : pathList) {
				mapPathMap.put(mp.getKey(), mp);
			}
		}

		// 加载路线锁列表
		List<PathLock> plList = PathLockBean.loadData(sqlSessionFactory);
		if (plList.size() > 0) {
			for (PathLock pathLock : plList) {
				pathLockMap.put(pathLock.getItem(), pathLock);
			}
		}

		// 加载站点
		stationMap = new HashMap<String, Station>();
		List<Station> stationList = StationBean.loadData(sqlSessionFactory);
		if (stationList.size() > 0) {
			for (Station s : stationList) {
				stationMap.put(s.getName(), s);
			}
		}
		List<Map<String, Object>> tempStations = StationBean.loadTempData(sqlSessionFactory);
		for (Map<String, Object> ts : tempStations) {
			String sn = (String) ts.get("name");
			Station s = stationMap.get(sn);
			if (s != null) {
				if (ts.get("lastData") != null) {
					s.setLastData((String) ts.get("lastData"));
				}
				if (ts.get("joinAgvId") != null) {
					s.setJoinAgvId((Integer) ts.get("joinAgvId"));
				}
				if (ts.get("lastJoinTime") != null) {
					s.setLastJoinTime((Date) ts.get("lastJoinTime"));
				}
				stationMap.put(s.getName(), s);
			}
		}

		// 加载限行区
		limitAreaMap = new HashMap<Integer, LimitArea>();
		List<LimitArea> limitAreaList = LimitAreaBean.loadData(sqlSessionFactory);
		if (limitAreaList.size() > 0) {
			for (LimitArea la : limitAreaList) {
				limitAreaMap.put(la.getId(), la);
			}
		}
		// 加载系统参数
		paramList = ParamBean.loadData(sqlSessionFactory, PCName);
		for (Map<String, String> p : paramList) {
			if (p.get("key").equals("chargeTime")) {// 充电时长
				chargeDuration = Integer.parseInt(p.get("value"));
				logger.info("充电时长：" + chargeDuration + "秒");
			}
			if (p.get("key").equals("localIp")) {// 本地IP地址
				localIp = p.get("value");
				logger.info("本地IP：" + localIp);
			}
			if (p.get("key").equals("localStationIp")) {//本地机台IP地址
				Main.localStationIpAddress = p.get("value");
				logger.info("本地机台监听IP" + Main.localStationIpAddress);
			}
			if(p.get("key").equals("lowBatteryChargerTime")) {//低电量充电时间
				Main.lowBatteryChargerTimes = Integer.parseInt(p.get("value"));
				logger.info("低电量充电时间:" + Main.lowBatteryChargerTimes + "分钟");
			}
		}
		// 连接websocket服务端
		webSocketConn();
	}

	/**
	 * 监听UDP端口
	 */
	public void initSocket() {

		int mwport = PropsUtil.getNumber(props, "mwport");
		Accept4Park ulis4Park = new Accept4Park(mainAction, mwport);
		pool.execute(ulis4Park);

		int agvport = PropsUtil.getNumber(props, "agvport");
		Accept4Agv ulis4Agv = new Accept4Agv(mainAction, agvport);
		pool.execute(ulis4Agv);

	}

	/**
	 * 向机台发送数据
	 * 
	 * @param data
	 * @param park
	 * @param note
	 */
	public void sendDataToPark(byte[] data, Park park, String note) {
		saveOutputLog(park.getName(), HexUtil.byte2HexStr(data), note, "Park", park.getName(),
				DateUtil.getTimeDate(new Date()));
		UDPUtil.sendData4Park(data, park.getIpAddress(), park.getPort());
		logger.info("-----------IP:" + park.getIpAddress() + ":" + park.getPort() + "数据:" + HexUtil.byte2HexStr(data)
				+ " ------------");
	}

	/**
	 * 向机台发送数据,有本地端口发送
	 * 
	 * @param data
	 * @param park
	 * @param note
	 */
	public void sendDataToParkWithLocalPort(byte[] data, Park park, String note) {
		saveOutputLog(park.getName(), HexUtil.byte2HexStr(data), note, "Park", park.getName(),
				DateUtil.getTimeDate(new Date()));
		UDPUtil.sendData4ParkWithLocalPort(data, park.getIpAddress(), park.getPort());
		logger.info("-----------IP:" + park.getIpAddress() + ":" + park.getPort() + "数据:" + HexUtil.byte2HexStr(data)
				+ " ------------");
	}

	/**
	 * 向中电二所发送数据流
	 * 
	 * @param data
	 * @param park
	 * @param note
	 */
	public void sendDataToZDES(byte[] data, Park park, String note) {
		saveOutputLog(park.getName(), HexUtil.byte2HexStr(data), note, "Park", park.getName(),
				DateUtil.getTimeDate(new Date()));
		UDPUtil.sendData4Park4ZDES(data, park.getXtIpAddress(), park.getXtPort());
		logger.info("-----------IP:" + park.getXtIpAddress() + ":" + park.getPort() + "数据:" + HexUtil.byte2HexStr(data)
				+ " ------------");
	}

	/**
	 * 向AGV发送数据
	 * 
	 * @param data
	 * @param note
	 * @param ctrlState
	 */
	public void sendDataToAgv(byte[] data, String note, int ctrlState) {
		String dstr = HexUtil.byte2HexStr(data);
		int agvId = data[1];
		saveOutputLog(dstr.substring(0, 2), dstr, note, "AGV", agvId + "", DateUtil.getTimeDate(new Date()));
		Agv agv = agvMap.get(agvId);
		if (agv != null) {
			String ip = agv.getIpAddress();
			int port = agv.getPort();
			try {
				UDPUtil.sendData4Agv(data, ip, port);
				// logger.info("++++send to agv:【" + agv.getId() + "】,time:" +
				// DateUtil.getTimeDate(new Date()));
			} catch (Exception e) {
				e.printStackTrace();
			}
			agv.setCtrlState(ctrlState);
			agv.setCtrlCommand(data);
			agv.setCtrlCommandStr(HexUtil.byte2HexStr(data));
			agv.setCtrlNote(note);
			agvMap.put(agv.getId(), agv);
			// 下发行驶指令时，清空AGV端的消息显示
			if (ctrlState == AgvState.XS.getCode()) {
				sendMsgByWs(agv.getId() + "", "");
			}
		}
	}

	/**
	 * 保存接收到的数据
	 * 
	 * @param dataHead
	 * @param data
	 * @param note
	 * @param clientType
	 * @param clinetNo
	 * @param inputTime
	 */
	public void saveInputLog(int port, String dataHead, String data, String note, String clientType, String clientNo,
			String inputTime) {
		input.info(inputTime + "," + clientType + "," + clientNo + "," + data + "," + note + "," + port);
	}

	/**
	 * 保存发出去的数据
	 * 
	 * @param dataHead
	 * @param data
	 * @param note
	 * @param clientType
	 * @param clientNo
	 * @param inputTime
	 */
	public void saveOutputLog(String dataHead, String data, String note, String clientType, String clientNo,
			String time) {
		String timeStr = DateUtil.getTimeDate(new Date());
		output.info(timeStr + "," + clientType + "," + clientNo + "," + note + "," + data);
	}

	public void insertPaths(int mapX, int mapY) {
		pool.execute(new Runnable() {
			@Override
			public void run() {
				SqlSession sqlSession = sqlSessionFactory.openSession();
				try {
					PathDao dao = sqlSession.getMapper(PathDao.class);
					Map<String, Integer> map = new HashMap<String, Integer>();
					map.put("mapX", mapX);
					map.put("mapY", mapY);
					dao.saveAgvPaths(map);
					sqlSession.commit();
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					sqlSession.close();
				}
			}
		});
	}

	public void saveParkLog(int parkId, String parkName, int agvId, String inTime) {
		pool.execute(new Runnable() {
			@Override
			public void run() {
				SqlSession sqlSession = sqlSessionFactory.openSession();
				try {
					ParkDao dao = sqlSession.getMapper(ParkDao.class);
					Map<String, String> map = new HashMap<String, String>();
					map.put("parkId", parkId + "");
					map.put("parkName", parkName);
					map.put("agvId", agvId + "");
					map.put("inTime", inTime);
					dao.saveParkingLog(map);
					sqlSession.commit();
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					sqlSession.close();
				}
			}
		});
	}

	/**
	 * 每天的凌晨1点删除多余的日志文件
	 */
	public void deleteLog() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, 1); // 控制时
		calendar.set(Calendar.MINUTE, 0); // 控制分
		calendar.set(Calendar.SECOND, 0); // 控制秒
		Date time = calendar.getTime(); // 得出执行任务的时间,此处为今天的凌晨1：00：00
		Timer timer = new Timer();
		timer.scheduleAtFixedRate(new TimerTask() {
			public void run() {
				String path = "d:/logs";
				List<File> list = FileUtil.getFileSort(path);
				for (int i = 0; i < list.size(); i++) {
					if (i >= 10) {
						list.get(i).delete();
					}
				}
			}
		}, time, 1000 * 60 * 60 * 24);// 这里设定将延时每天固定执行
	}

	/**
	 * 重置系统数据
	 */
	public void resetData() {
		// 加载交管区列表
//		controlAreaMap = new HashMap<Integer, ControlArea>();
//		List<ControlArea> controlAreaList = ControlAreaBean.loadData(dataSource);
//		for(ControlArea ca:controlAreaList){
//			controlAreaMap.put(ca.getId(), ca);
//		}
		// 加载AGV列表
//		agvMap = new HashMap<Integer, Agv>();
//		List<Agv> agvList = AgvBean.loadData(dataSource);
//		for(Agv agv:agvList){
//			agv.setParkName("");
//			agv.setLastData("");
//			agv.setCtrlNote("");
//			agv.setLastTime("");
//			agv.setCtrlCommandStr("");
//			agvMap.put(agv.getId(), agv);
//		}

		// 清空任务列表
		// jobList = new ArrayList<Job>();
		// 清空交管等待列表
		// waitAgvList = new ArrayList<TrafficWait>();
	}

	/**
	 * 充电计时
	 */
	private void stopCharge() {
		for (Map.Entry<Integer, Agv> m : agvMap.entrySet()) {
			Agv cagv = m.getValue();
			Date currentTime = new Date();
			long t2 = currentTime.getTime();
			if (cagv.getState() == AgvState.CD.getCode() && cagv.getCtrlState() == AgvState.CD.getCode()
					&& cagv.getBeginChargeTime() != null) {
				Date chargeTime = cagv.getBeginChargeTime();
				long t1 = chargeTime.getTime();
				long t3 = (t2 - t1) / 1000;
				long ct = (long) chargeDuration;// 秒钟
				logger.info("AGV:" + cagv.getId() + "号已经充电" + t3 + "秒");
				if (t3 > ct) {
					int type = TransferType.WC.getCode();// 传输完成
					byte[] data = CommandUtil.transfer(cagv.getId(), type);
					String note = "AGV" + cagv.getId() + "对接完成回到主路";
					sendDataToAgv(data, note, AgvState.XS.getCode());// ctrlState,1、行驶
				}
			}
		}
	}

	/**
	 * 定时以fins协议读取机台的寄存器
	 */
	public void readFinsData() {
		for (Map.Entry<String, Station> m : stationMap.entrySet()) {
			Station station = m.getValue();
			if (station.getProtocol().equals("fins")) {
				// 读取PLC写入值
				// String plcIp = station.getIpAddress();
				String plcIp = "192.168.250.1";
				// String pcIp = localIp;
				String pcIp = "192.168.250.117";
				int action = 1;// fins读操作
				// int readTar = station.getReadTar();//PLC写入寄存器地址
				int readTar = 32413;
				// int port = station.getPort();//PLC接收端口
				int port = 9600;
				byte[] sendByte1 = CommandUtil.getFinsHead(plcIp, pcIp, action, readTar);
				UDPUtil.sendData4Fins(sendByte1, plcIp, port, action, mainAction, 1);
				byte[] result1 = UDPUtil.sendData4Fins(sendByte1, plcIp, port, action, mainAction, 1);
				logger.info("PLC写入值：" + HexUtil.byte2HexStr(result1));
				// 读取PC写入值
//				int finsWritePort = 9887;
//				int writeTar = station.getWriteTar();
//				byte[] sendByte2 = CommandUtil.getFinsHead(plcIp, pcIp, action, writeTar);
//				UDPUtil.sendData4Fins(sendByte2, plcIp, port, finsWritePort, action, mainAction, 3);
				// byte[] result2 = UDPUtil.sendData4Fins(sendByte2, plcIp, port, finsWritePort,
				// action, mainAction, 2);
				// logger.info("调度写入值：" + HexUtil.byte2HexStr(result2));
			}
		}
	}

	public void webSocketConn() {
		String webServer = PropsUtil.getString(props, "webServer");
		try {
			String url = "ws://" + webServer + ":8012/echo/username=sys&src=svr";
			wsClient = new WebSocketClient(new URI(url), new Draft_6455()) {
				@Override
				public void onOpen(ServerHandshake serverHandshake) {
					logger.info("握手成功！");
				}

				@Override
				public void onMessage(String msg) {
					logger.info("收到消息==========" + msg);
					if (msg.equals("over")) {
						wsClient.close();
					}
				}

				@Override
				public void onClose(int i, String s, boolean b) {
					logger.info("链接已关闭");
					wsClient = null;
				}

				@Override
				public void onError(Exception e) {
					e.printStackTrace();
					logger.info("发生错误已关闭");
					wsClient = null;
				}
			};
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		wsClient.connect();
	}

	public void sendMsgByWs(String agvNo, String msg) {
		if (wsClient == null) {
			logger.info("没有websocket连接，无法发送消息！");
		} else {
			String msgp = "{receiver:'no" + agvNo + "_agv',data:'" + msg + "'}";
			wsClient.send(msgp);
		}
	}

	public void websocketClose() {
		wsClient.close();
		wsClient = null;
	}

}